tree grammar BPSLWalker;

options{
	tokenVocab=BPSL;
	ASTLabelType=CommonTree;
}

@header{
	package modelbuilding.analysis.bpsl;
	
	import modelbuilding.generation.*;
	import java.util.Map;
	import java.util.HashMap;
	import modelbuilding.analysis.bpsl.*;
}

/*The AST has the form of a flat tree (list) whos elements are trees with height 1

List -> ( CLASSDEF-Tree | TYPEDVARDEF-Tree | METHODDEF-Tree | )+, PREDICATE1, PREDICATE2, PREDICATE3,..
with	:	
CLASSDEF-Tree : root "CLASSDEF" - children ID1, ID2, ID3,...
...
PREDICATE-Tree : root "PREDICATE" - children ID1, ID2 ( exactly 2 children )

The generated treewalker needs as input a tree of the described structure. The AST generated by the associated
parser grammar produces such a tree from the input design pattern specification file
*/


/*simple production rule			
specification	:	(  ^(CLASSDEF ID+ ) |  ^(TYPEDVARDEF ID+ ) | ( ^(METHODDEF ID+ ) )+ ( ^(PREDICATE ID ID) )*
			;
			
corresponeds to			Variable definitios - VarDef Block					|	Formula - Predicate Block
*/

/*Production rule extended with actions to verify some rules for a valid SBPSL especification
--> A variable can be declared only once.
--> A variable used in the formula has to be declared.
--> A predicate has to be defined for the domain of its arguments		
*/
specification	returns [ModelData modelData]
			@init{
				Map<String, BPSLTermType> symbols = new HashMap<String, BPSLTermType>();
				BPSLPredicateSpace predicates = BPSLPredicateSpace.getInstance();
				modelData = new ModelData();
				String nameSpace;
			 }
			:	a=PATTERNNAME { nameSpace = $a.text; nameSpace = nameSpace.trim(); nameSpace = nameSpace.substring(1); }
				(
				^(CLASSDEF (a=ID
				{	
					if ( ! symbols.containsKey($a.text) ) {
						//add variable to the symbol table
						symbols.put($a.text, BPSLTermType.CLASS);
						//add term as vertex to the graph under construction
						modelData.addVertexData( new VertexData( nameSpace + "." + $a.text, $a.line, $a.pos, BPSLTermType.CLASS ) );
					}
					else {
						// variable already used. treat errror
					}
				})+
				)
			|	

				^(TYPEDVARDEF (a=ID
				{
					if ( ! symbols.containsKey($a.text) ) {
						//add variable to the symbol table
						symbols.put($a.text, BPSLTermType.TYPEDVARIABLE);
						//add term as vertex to the graph under construction
						modelData.addVertexData( new VertexData( nameSpace + "." + $a.text, $a.line, $a.pos, BPSLTermType.TYPEDVARIABLE ) );
					}
					else {
						// variable allready used. treat errror
					}	
				})+
				)
				
			|
	
				^(METHODDEF (a=ID
				{
					if ( ! symbols.containsKey($a.text) ) {
						//add variable to the symbol table
						symbols.put($a.text, BPSLTermType.METHOD);
						//add term as vertex to the graph under construction
						modelData.addVertexData( new VertexData( nameSpace + "." + $a.text, $a.line, $a.pos, BPSLTermType.METHOD) );
					}
					else {
						// variable allready used. treat errror
					}	
				})+
				)
			)+
				
				( ^(c=PREDICATE a=ID b=ID)
				{ 
					BPSLTermType aType, bType;
					//verify if ID a has been declared and get his type
					aType = symbols.get($a.text);
					//verify if ID b has been declard and get his type
					bType = symbols.get($b.text);
					//if both have been declared verify if predicate is defined for this domain
					if (aType != null && bType != null) {
						//if predicate is defined add adge to graph
						if ( predicates.isDefinedOnDomain($c.text, symbols.get($a.text), symbols.get($b.text)) ){
							//add atom as edge to the graph under construction
							modelData.addEdgeData( new EdgeData( $c.line, $c.pos, BPSLPredicateType.getEnum( $c.text ), nameSpace + "." + $a.text, nameSpace + "." + $b.text ) );   	
						}
						//else treat error
						else {
						} 
					
					}
					//else treat error
					else {
					}
						
				}
				)*
			;
